10分で学ぶC言語
Cは効率性とハードウェアに近い機能で知られる強力な汎用プログラミング言語です。このチュートリアルではCプログラミングの基礎をカバーし、言語を素早く理解できるようにします。
1. 最初のCプログラムを書く
まずは古典的な「Hello, World!」プログラムから始めましょう。hello.c
という名前のファイルを作成し、以下のコードを入力します:
#include <stdio.h>
int main() {
printf("Hello, World!\n");
return 0;
}
ファイルを保存し、GCCなどのCコンパイラを使ってコンパイルします:
gcc hello.c -o hello
./hello
出力は以下のようになります:
Hello, World!
このシンプルなプログラムはCの基本構造を示しています:
#include <stdio.h>
は標準入出力ライブラリをインクルードしますint main()
はプログラムのエントリーポイントですprintf()
はテキスト出力を表示しますreturn 0
は正常な実行を示します
2. 基本構文
Cは構造化された構文を使用し、セミコロンで文を終了し、中括弧{}
でコードブロックを定義します。
// これは単一行コメントです
/* これは複数行コメントです */
#include <stdio.h>
int main() {
printf("Hello, World!\n");
return 0;
}
Cの基本構文ルール:
- セミコロン: すべての文はセミコロン
;
で終了する必要があります - コメント: 単一行コメントは
//
を使用し、複数行コメントは/* */
を使用します - コードブロック: 中括弧
{}
で定義されます - 大文字小文字の区別: Cは大文字小文字を区別します(
main
とMain
は異なります)
3. 変数とデータ型
Cは静的型付け言語であり、使用前に変数の型を宣言する必要があります。
基本的な変数命名ルール:
- 変数名には文字、数字、アンダースコアを含めることができます
- 変数名は数字で始めることはできません
- 変数名は大文字小文字を区別します
- Cのキーワードは変数名として使用できません
Cの主なデータ型:
- int: 整数(例:
42
、-10
) - float: 浮動小数点数(例:
3.14
、-2.5
) - double: 倍精度浮動小数点数
- char: 単一文字(例:
'A'
、'z'
) - void: 型なし
int age = 25;
float temperature = 36.5;
double pi = 3.14159265359;
char grade = 'A';
3.1 整数型
Cはさまざまなサイズの整数型を提供します:
char small_number = 100; // 通常1バイト
short medium_number = 32000; // 通常2バイト
int regular_number = 1000000; // 通常4バイト
long large_number = 1000000000; // 通常4または8バイト
3.2 浮動小数点型
float single_precision = 3.14f;
double double_precision = 3.14159265359;
long double extended_precision = 3.14159265358979323846L;
3.3 文字型
文字はASCIIエンコーディングを使用して整数として格納されます:
char letter = 'A';
char digit = '7';
char newline = '\n';
char tab = '\t';
4. 定数
定数はプログラム実行中に変更できない固定値です:
const int MAX_SIZE = 100;
const float PI = 3.14159;
const char NEWLINE = '\n';
#define MAX_USERS 1000
#define PI 3.14159
5. 入力と出力
Cは入出力操作にstdio.h
の関数を使用します。
5.1 printf()による出力
#include <stdio.h>
int main() {
int age = 25;
float height = 1.75;
char name[] = "John";
printf("Hello, %s!\n", name);
printf("You are %d years old\n", age);
printf("Your height is %.2f meters\n", height);
return 0;
}
一般的なフォーマット指定子:
%d
- 整数%f
- float/double%c
- 文字%s
- 文字列%p
- ポインタ
5.2 scanf()による入力
#include <stdio.h>
int main() {
int age;
float height;
char name[50];
printf("Enter your name: ");
scanf("%s", name);
printf("Enter your age: ");
scanf("%d", &age);
printf("Enter your height: ");
scanf("%f", &height);
printf("Hello %s, you are %d years old and %.2f meters tall\n",
name, age, height);
return 0;
}
6. 演算子
Cはさまざまな計算のための豊富な演算子セットを提供します。
6.1 算術演算子
int a = 10, b = 3;
printf("Addition: %d\n", a + b); // 13
printf("Subtraction: %d\n", a - b); // 7
printf("Multiplication: %d\n", a * b); // 30
printf("Division: %d\n", a / b); // 3
printf("Modulus: %d\n", a % b); // 1
6.2 比較演算子
int x = 5, y = 10;
printf("Equal: %d\n", x == y); // 0 (false)
printf("Not equal: %d\n", x != y); // 1 (true)
printf("Greater than: %d\n", x > y); // 0
printf("Less than: %d\n", x < y); // 1
6.3 論理演算子
int a = 1, b = 0;
printf("AND: %d\n", a && b); // 0
printf("OR: %d\n", a || b); // 1
printf("NOT: %d\n", !a); // 0
6.4 ビット演算子
unsigned int a = 5; // 2進数で0101
unsigned int b = 3; // 2進数で0011
printf("AND: %d\n", a & b); // 1 (0001)
printf("OR: %d\n", a | b); // 7 (0111)
printf("XOR: %d\n", a ^ b); // 6 (0110)
printf("NOT: %d\n", ~a); // システムに依存
printf("Left shift: %d\n", a << 1); // 10 (1010)
printf("Right shift: %d\n", a >> 1); // 2 (0010)
7. 制御フロー
Cはプログラム実行を管理するためのいくつかの制御フロー文を提供します。
7.1 if文
int age = 20;
if (age >= 18) {
printf("Adult\n");
} else if (age >= 13) {
printf("Teen\n");
} else {
printf("Child\n");
}
7.2 switch文
int day = 3;
switch (day) {
case 1:
printf("Monday\n");
break;
case 2:
printf("Tuesday\n");
break;
case 3:
printf("Wednesday\n");
break;
default:
printf("Other day\n");
}
7.3 forループ
for (int i = 0; i < 5; i++) {
printf("i = %d\n", i);
}
7.4 whileループ
int count = 0;
while (count < 5) {
printf("Count: %d\n", count);
count++;
}
7.5 do-whileループ
int count = 0;
do {
printf("Count: %d\n", count);
count++;
} while (count < 5);
7.6 breakとcontinue
for (int i = 0; i < 10; i++) {
if (i == 5) {
break; // ループを終了
}
if (i % 2 == 0) {
continue; // 偶数をスキップ
}
printf("i = %d\n", i); // 出力: 1, 3
}
8. 配列
配列は同じ型の複数の値を格納します。
8.1 一次元配列
int numbers[5] = {1, 2, 3, 4, 5};
// 要素へのアクセス
printf("First element: %d\n", numbers[0]);
printf("Last element: %d\n", numbers[4]);
// 要素の変更
numbers[0] = 10;
// 配列のループ処理
for (int i = 0; i < 5; i++) {
printf("numbers[%d] = %d\n", i, numbers[i]);
}
8.2 多次元配列
int matrix[2][3] = {
{1, 2, 3},
{4, 5, 6}
};
// 要素へのアクセス
printf("matrix[1][2] = %d\n", matrix[1][2]); // 6
// 2次元配列のループ処理
for (int i = 0; i < 2; i++) {
for (int j = 0; j < 3; j++) {
printf("%d ", matrix[i][j]);
}
printf("\n");
}
9. 文字列
Cでは、文字列はヌル文字\0
で終了する文字の配列です。
char greeting[] = "Hello"; // 自動的にヌル終端文字を含む
char name[20] = "John";
// string.hの文字列関数
#include <string.h>
char str1[20] = "Hello";
char str2[20] = "World";
printf("Length: %lu\n", strlen(str1)); // 5
strcpy(str1, str2); // str2をstr1にコピー
printf("After copy: %s\n", str1); // World
if (strcmp(str1, str2) == 0) {
printf("Strings are equal\n");
}
10. 関数
関数は特定のタスクを実行する再利用可能なコードブロックです。
10.1 関数の定義と呼び出し
#include <stdio.h>
// 関数宣言
int add(int a, int b);
int main() {
int result = add(5, 3);
printf("5 + 3 = %d\n", result);
return 0;
}
// 関数定義
int add(int a, int b) {
return a + b;
}
10.2 戻り値のない関数
void greet(char name[]) {
printf("Hello, %s!\n", name);
}
int main() {
greet("Alice");
return 0;
}
10.3 再帰関数
int factorial(int n) {
if (n <= 1) {
return 1;
}
return n * factorial(n - 1);
}
int main() {
printf("5! = %d\n", factorial(5)); // 120
return 0;
}
11. ポインタ
ポインタはメモリアドレスを格納する変数です。
11.1 基本的なポインタの使用
int number = 42;
int *ptr = &number; // ptrはnumberのアドレスを格納
printf("Value: %d\n", number); // 42
printf("Address: %p\n", &number); // メモリアドレス
printf("Pointer value: %d\n", *ptr); // 42 (間接参照)
// ポインタを通じて値を変更
*ptr = 100;
printf("New value: %d\n", number); // 100
11.2 ポインタと配列
int numbers[] = {1, 2, 3, 4, 5};
int *ptr = numbers; // 最初の要素を指す
printf("First element: %d\n", *ptr); // 1
printf("Second element: %d\n", *(ptr + 1)); // 2
// 配列名は本質的に最初の要素へのポインタ
for (int i = 0; i < 5; i++) {
printf("numbers[%d] = %d\n", i, *(numbers + i));
}
11.3 ポインタと関数
void swap(int *a, int *b) {
int temp = *a;
*a = *b;
*b = temp;
}
int main() {
int x = 5, y = 10;
printf("Before swap: x=%d, y=%d\n", x, y);
swap(&x, &y);
printf("After swap: x=%d, y=%d\n", x, y);
return 0;
}
12. 構造体
構造体は関連する変数をグループ化できます。
12.1 構造体の定義と使用
#include <stdio.h>
#include <string.h>
// 構造体定義
struct Student {
char name[50];
int age;
float gpa;
};
int main() {
// 構造体変数の作成
struct Student student1;
// 値の代入
strcpy(student1.name, "Alice");
student1.age = 20;
student1.gpa = 3.8;
// 構造体メンバへのアクセス
printf("Name: %s\n", student1.name);
printf("Age: %d\n", student1.age);
printf("GPA: %.2f\n", student1.gpa);
return 0;
}
12.2 ポインタを使った構造体
struct Point {
int x;
int y;
};
int main() {
struct Point p1 = {10, 20};
struct Point *ptr = &p1;
printf("Coordinates: (%d, %d)\n", ptr->x, ptr->y);
return 0;
}
13. 動的メモリ割り当て
Cは動的メモリ管理のための関数を提供します。
13.1 malloc, calloc, realloc, free
#include <stdio.h>
#include <stdlib.h>
int main() {
// 5つの整数のためのメモリを割り当て
int *numbers = (int*)malloc(5 * sizeof(int));
if (numbers == NULL) {
printf("Memory allocation failed!\n");
return 1;
}
// 配列の初期化
for (int i = 0; i < 5; i++) {
numbers[i] = i * 10;
}
// 配列の表示
for (int i = 0; i < 5; i++) {
printf("numbers[%d] = %d\n", i, numbers[i]);
}
// 割り当てられたメモリの解放
free(numbers);
return 0;
}
13.2 動的文字列割り当て
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main() {
char *name = (char*)malloc(50 * sizeof(char));
if (name != NULL) {
strcpy(name, "Dynamic string");
printf("Name: %s\n", name);
free(name);
}
return 0;
}
14. ファイル操作
Cはファイルの読み書きのための関数を提供します。
14.1 ファイルへの書き込み
#include <stdio.h>
int main() {
FILE *file = fopen("example.txt", "w");
if (file == NULL) {
printf("Error opening file!\n");
return 1;
}
fprintf(file, "Hello, File!\n");
fprintf(file, "This is a test.\n");
fclose(file);
printf("File written successfully.\n");
return 0;
}
14.2 ファイルからの読み込み
#include <stdio.h>
int main() {
FILE *file = fopen("example.txt", "r");
if (file == NULL) {
printf("Error opening file!\n");
return 1;
}
char buffer[100];
while (fgets(buffer, sizeof(buffer), file) != NULL) {
printf("%s", buffer);
}
fclose(file);
return 0;
}
15. プリプロセッサディレクティブ
プリプロセッサディレクティブはコンパイル前に処理されます。
15.1 #include
#include <stdio.h> // システムヘッダーファイル
#include "myheader.h" // ユーザーヘッダーファイル
15.2 #define
#define PI 3.14159
#define MAX(a, b) ((a) > (b) ? (a) : (b))
int main() {
double area = PI * 5 * 5;
int larger = MAX(10, 20);
printf("Area: %.2f\n", area);
printf("Larger number: %d\n", larger);
return 0;
}
15.3 条件付きコンパイル
#define DEBUG 1
int main() {
#ifdef DEBUG
printf("Debug mode enabled\n");
#endif
#if DEBUG == 1
printf("Debug level 1\n");
#elif DEBUG == 2
printf("Debug level 2\n");
#else
printf("No debug\n");
#endif
return 0;
}
16. エラー処理
Cには組み込みの例外処理がないため、戻り値とエラーコードを使用します。
#include <stdio.h>
#include <errno.h>
#include <string.h>
int main() {
FILE *file = fopen("nonexistent.txt", "r");
if (file == NULL) {
printf("Error opening file: %s\n", strerror(errno));
return 1;
}
fclose(file);
return 0;
}
この包括的なCチュートリアルは、Cプログラミングを始めるために必要な基本的な概念をカバーしています。これらの例を練習し、言語に慣れてきたら、リンクリスト、関数ポインタ、マルチファイルプログラムなどのより高度なトピックを探求してください。